#include "WProgram.h"
#include "RGBStrip.h"

RGBStrip::RGBStrip(unsigned int S, unsigned int D, unsigned int C, unsigned int L, unsigned int LEDCount, unsigned char * displayAddr )
{
  _S = S;
  _D = D;
  _L = L;
  _C = C;
  _LEDCount = LEDCount;
  _ClockWait = (LEDCount * 250)/1000;   //This is the required delay between sending a bit and the clock line being fired.
  Display = displayAddr;                //You can tweak this value lower until you find LEDs on the end of your chain misbehaving
                                        //In fact, if you are running less than a few hundred LEDs you can get away with zero here.
                                        //250nSec per LED is the specified value for the chip.

  //Set up our pins to connect to the LED strip.
  pinMode(_S, OUTPUT);
  pinMode(_D, OUTPUT);
  pinMode(_C, OUTPUT);
  pinMode(_L, OUTPUT);
  digitalWrite(_S, LOW);
  digitalWrite(_D, LOW);
  digitalWrite(_L, LOW);
  digitalWrite(_C, LOW);

}


void RGBStrip::sPulse()
{
  //Pulse the S line on the LEDs. This will make any LEDs that are fading do their thing.
  //If the double speed bit IS set then two fades will occur. Once each time the pin is inverted.
  
  digitalWrite(_S, 1);
  delayMicroseconds(100);
  digitalWrite(_S, 0);
  delayMicroseconds(100);
}



void RGBStrip::sendByte(unsigned char it)
{
  //Send out one byte, don't forget to LATCH it by calling
  //Note that for LARGE number of LEDs you may need to slow things down a little here.  
  digitalWrite(_C, LOW);

  char x;
     for(x=0;x < 8; x++)
    { 
    if(B10000000 & it)
      digitalWrite(_D, HIGH); 
    else
      digitalWrite(_D, LOW); 
    it = it<<1;
    // Wait here needs to be 250 x Number of LEDs nano seconds to allow data to propagate before being clocked in
    delayMicroseconds(_ClockWait);
    digitalWrite(_C, HIGH);
    digitalWrite(_C, LOW);

    }
}


void RGBStrip::latch()
{
  digitalWrite(_L, HIGH);
  delayMicroseconds(1);  // spec sheet specifies minimum latch pulse of 1us
  digitalWrite(_L, LOW);
}

void RGBStrip::runfader(unsigned int y, unsigned int d)
{
  //Pulse the fader y times with delay d between each pulse
  int x;
  for(x=0;x<y;x++)
  {
    digitalWrite(_S, LOW);
    delay(d);
    digitalWrite(_S, HIGH);
    delay(d);
  }
}


void RGBStrip::displaySend()
{
  //Send out the global array of bytes and then latch them in
  int x=_LEDCount;
  while(x > 0)
  {
    sendByte(  Display[--x]);   
  }
  //latch();
}

void RGBStrip::SetLed(unsigned int Led, unsigned int Color)
{
    //This will send the data to set an individual LED, no effect on any others
    //L2ggrrbb
    uint8_t i;
    uint8_t x;
 
    x = _LEDCount - Led; //How many to clock out before we send this one

   for(i=0 ; i < x ; i++)
   {
    sendByte(0); 
   }
  
  //               L2ggrrbb
  sendByte(Color);
  while(i++ < _LEDCount)
    sendByte(0);
  latch(); 
}

void RGBStrip::displaySetSection(unsigned int startled, unsigned int endled, unsigned char ledvalue)
{
  //Set a range of LEDs in the memory buffer.
  //Don't forget to call SendDisplay to send the buffer to the LEDs once done!
  while(startled <= endled)
  {
    Display[startled++] = ledvalue;
  }
}

